//
//  NSObject+HACSwizzling.m
//  HACRouter
//
//  Created by Chengjie on 2019/5/23.
//

#import "NSObject+HACSwizzling.h"
#import <objc/runtime.h>

void hac_swizzleInstanceMethod(Class cls_, SEL origSel_, SEL swizzledSel_) {
    Method originalMethod = class_getInstanceMethod(cls_, origSel_);
    Method swizzledMethod = class_getInstanceMethod(cls_, swizzledSel_);
    BOOL didAddMethod = class_addMethod(cls_,
                                        origSel_,
                                        method_getImplementation(swizzledMethod),
                                        method_getTypeEncoding(swizzledMethod));
    if (didAddMethod) {
        class_replaceMethod(cls_,
                            swizzledSel_,
                            method_getImplementation(originalMethod),
                            method_getTypeEncoding(originalMethod));
    } else {
        method_exchangeImplementations(originalMethod, swizzledMethod);
    }
}

void hac_swizzleClassMethod(Class cls_, SEL origSel_, SEL swizzledSel_) {
    Class metaClass = object_getClass(cls_);
    Method originalMethod = class_getClassMethod(metaClass, origSel_);
    Method swizzledMethod = class_getClassMethod(metaClass, swizzledSel_);
    BOOL didAddMethod = class_addMethod(metaClass,
                                        origSel_,
                                        method_getImplementation(swizzledMethod),
                                        method_getTypeEncoding(swizzledMethod));
    if (didAddMethod) {
        class_replaceMethod(metaClass,
                            swizzledSel_,
                            method_getImplementation(originalMethod),
                            method_getTypeEncoding(originalMethod));
    } else {
        method_exchangeImplementations(originalMethod, swizzledMethod);
    }
}

Class hac_getClass(NSString *prefix_, NSString *suffix_) {
    return NSClassFromString([prefix_ stringByAppendingString:suffix_]);
}

Class hac_getMetaClass(NSString *prefix_, NSString *suffix_) {
    return objc_getMetaClass([prefix_ stringByAppendingString:suffix_].UTF8String);
}

@implementation NSObject (HACSwizzling)

+ (void)hac_swizzleInstanceMethodWithClass:(Class)cls_ originalMethod:(SEL)origSel_ swizzledMethod:(SEL)swizzledSel_ {
    hac_swizzleInstanceMethod(cls_, origSel_, swizzledSel_);
}

+ (void)hac_swizzleClassMethodWithClass:(Class)cls_ originalMethod:(SEL)origSel_ swizzledMethod:(SEL)swizzledSel_ {
    hac_swizzleClassMethod(cls_, origSel_, swizzledSel_);
}

+ (Class)hac_getClassWithPrefix:(NSString *)prefix_ suffix:(NSString *)suffix_ {
    return hac_getClass(prefix_, suffix_);
}

@end
